package models

import (
	"time"
	"github.com/astaxie/beego/orm"
	"strconv"
	"read.com/admin/libs"
	"encoding/base64"
	"fmt"
)

type User struct {
	Id           int       `orm:"column(id);auto"`
	UserId       string    `orm:"column(user_id);size(8)" description:"用户ID"`
	Status       int8      `orm:"column(status)" description:"用户状态"`
	Nickname     string    `orm:"column(nickname);size(255)" description:"昵称"`
	Avatar       int8      `orm:"column(avatar)" description:"是否有头像"`
	Gender       int8      `orm:"column(gender)" description:"性别"`
	Coin         int64     `orm:"column(coin)" description:"书币"`
	Gift         int64     `orm:"column(gift)" description:"书券"`
	VipEnd       time.Time `orm:"column(vip_end);type(datetime)" description:"VIP结束时间"`
	SerialId     string    `orm:"column(serial_id);size(32)" description:"序列编号"`
	RegApp       int       `orm:"column(reg_app)" description:"注册APP"`
	RegOs        int8      `orm:"column(reg_os)" description:"注册OS"`
	RegIp        string    `orm:"column(reg_ip);size(15)" description:"注册IP"`
	RegDate      time.Time `orm:"column(reg_date);type(datetime)" description:"注册日期"`
	LoginSession string    `orm:"column(login_session);size(32)" description:"登录会话ID"`
	LoginCnt     int64     `orm:"column(login_cnt)" description:"累计登录次数"`
	PayCnt       int64     `orm:"column(pay_cnt)" description:"累计充值金额"`
	CoinCnt      int64     `orm:"column(coin_cnt)" description:"累计书币数量"`
	GiftCnt      int64     `orm:"column(gift_cnt)" description:"累计书券数量"`
	LoginDate    time.Time `orm:"column(login_date);type(datetime)" description:"登录日期"`
}

type FormatUser struct {
	Province string
	City     string
	User
}

func (t *User) TableName() string {
	return "user"
}

func init() {
	orm.RegisterModel(new(User))
}

func GetTotalCount() int {
	o := orm.NewOrm()
	count := 0
	o.Raw("select count(*) from user").QueryRow(&count)
	return count
}

func GetTodayCount() int {
	start := time.Now().Format("2006-01-02 00:00:00")
	end := time.Now().AddDate(0, 0, 1).Format("2006-01-02 00:00:00")
	o := orm.NewOrm()
	count := 0
	o.Raw("select count(*) from user where reg_date >= ? and reg_date < ?", start, end).QueryRow(&count)
	return count
}

func GetVipUserCount() int {
	o := orm.NewOrm()
	now := time.Now().Format("2006-01-02 15:04:05")
	count := 0
	o.Raw("select count(*) from user where vip_end > ?", now).QueryRow(&count)
	return count
}

func GetTodayVipCount() int {
	o := orm.NewOrm()
	start := time.Now().Format("2006-01-02 00:00:00")
	end := time.Now().AddDate(0, 0, 1).Format("2006-01-02 00:00:00")
	itemIds := make([]int, 0)
	o.Raw("select pc.item_id from pay_confirm pc,user u where u.user_id = pc.user_id and pc.commit_date >= ? and pc.commit_date < ?", start, end).QueryRows(&itemIds)
	count := 0
	for _, item := range itemIds {
		if pay, find := payItemHash[item]; find {
			if pay.Type != 1 {
				count ++
			}
		}
	}
	return count
}

func GetUserList(page int, pageSize int, userId int, name string) ([]map[string]string, int64,map[int]map[string]string) {
	o := orm.NewOrm()
	offset := (page - 1) * pageSize
	formatUsers := make([]*FormatUser, 0)
	count := 0
	if userId == 0 {
		sqlStr := "select u.*,uw.province,uw.city from user u inner join user_wxmp uw on(u.user_id = uw.user_id) where u.nickname like '%" + name + "%' order by id asc limit " + strconv.Itoa(offset) + "," + strconv.Itoa(pageSize)
		o.Raw(sqlStr).QueryRows(&formatUsers)
		sqlCount := "select count(*) from user u inner join user_wxmp uw on(u.user_id = uw.user_id) where u.nickname like '%" + name + "%'"
		o.Raw(sqlCount).QueryRow(&count)
	} else {
		sqlStr := "select u.*,uw.province,uw.city from user u inner join user_wxmp uw on(u.user_id = uw.user_id) where u.user_id = ? and u.nickname like '%" + name + "%' order by id asc limit " + strconv.Itoa(offset) + "," + strconv.Itoa(pageSize)
		o.Raw(sqlStr, userId).QueryRows(&formatUsers)
		sqlCount := "select count(*) from user u inner join user_wxmp uw on(u.user_id = uw.user_id) where u.user_id = ? and u.nickname like '%" + name + "%'"
		o.Raw(sqlCount, userId).QueryRow(&count)
	}

	results := make([]map[string]string, 0)
	for k, formatUser := range formatUsers {
		var isVip string
		if libs.CompareTime(formatUser.VipEnd, time.Now()) == -1 {
			isVip = "否"
		} else {
			isVip = "是"
		}
		payTimes := 0
		sqlCount := "select count(*) from pay_confirm where user_id = ?"
		o.Raw(sqlCount, formatUser.UserId).QueryRow(&payTimes)
		nickname, _ := base64.StdEncoding.DecodeString(formatUser.Nickname)
		appName := ""
		if app, find := appHash[formatUser.RegApp]; find {
			appName = app.AppName
		}
		restDay := (formatUser.VipEnd.Unix()-time.Now().Unix())/24/3600
		if restDay <= 0 {
			restDay = 0
		}
		result := map[string]string{
			"sort":      strconv.Itoa(k + 1),
			"userId":    formatUser.UserId,
			"nickname":  string(nickname),
			"sex":       strconv.Itoa(int(formatUser.Gender)),
			"appName":   appName,
			"appId":     strconv.Itoa(formatUser.RegApp),
			"area":      formatUser.Province + " " + formatUser.City,
			"regDate":   formatUser.RegDate.Format("2006-01-02 15:04:05"),
			"isVip":     isVip,
			"restDay":   strconv.FormatInt(restDay, 10),
			"loginDate": "0000-00-00 00:00:00",
			"payCnt":    strconv.Itoa(int(formatUser.PayCnt)),
			"coinCnt":   strconv.Itoa(int(formatUser.CoinCnt)),
			"coin":      strconv.Itoa(int(formatUser.Coin)),
			"payTimes":  strconv.Itoa(payTimes),
			"gift":      strconv.Itoa(int(formatUser.Gift)),
		}
		if !formatUser.LoginDate.IsZero() {
			result["loginDate"] = formatUser.LoginDate.Format("2006-01-02 15:04:05")
		}
		results = append(results, result)
	}
	tableHead := map[int]map[string]string{
		0:{"sort":"序号"},
		1:{"userId":"用户Id"},
		2:{"nickname":"用户名"},
		3:{"sex":"性别"},
		4:{"appName":"用户来源"},
		5:{"area":"地区"},
		6:{"isVip":"是否Vip"},
		7:{"regDate":"注册时间"},
		8:{"restDay":"Vip剩余天长"},
		9:{"loginDate":"最后一次登录时间"},
		10:{"payCnt":"累计充值总额"},
		11:{"payTimes":"累计充值次数"},
		12:{"coinCnt":"累计获得书币"},
		13:{"coin":"书币余额"},
		14:{"gift":"书券余额"},
	}
	return results, int64(count),tableHead
}

func GiveUserPresent(userId string, appId int, itemType int, num int, reason string) error {
	o := orm.NewOrm()
	//  1 书币, 2 书券, 3 vip
	// 更新 user 表
	user := &User{UserId: userId}
	err := o.Read(user, "user_id")
	if err != nil {
		fmt.Println("user not found", err)
		return err
	}
	if itemType == 1 {
		user.Coin = user.Coin + int64(num)
		user.CoinCnt = user.CoinCnt + int64(num)
	}
	if itemType == 2 {
		user.Gift = user.Gift + int64(num)
		user.GiftCnt = user.GiftCnt + int64(num)
	}
	if itemType == 3 {
		if !user.VipEnd.IsZero() {

		} else {

		}

	}
	if _, err := o.Update(user); err != nil {
		fmt.Println("update user error", err)
		return err
	}
	// 更新 log_bill 表
	err = AddLog(userId, appId, itemType, num, reason)
	if err != nil {
		return err
	}
	return nil
}
